﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
using HigLabo.Core;

namespace HigLabo.Net.WindowsLive
{
    /// <summary>
    /// 
    /// </summary>
    public partial class WindowsLiveClient 
    {
        public override String GetAuthorizeUrl(OAuth2ResponseType responseType)
        {
            Func<String, String> f = HttpClient.UrlEncode;
            return String.Format("https://oauth.live.com/authorize?response_type={0}&client_id={1}&redirect_uri={2}"
                , responseType.ToStringFromEnum().ToLower(), f(this.ClientID), f(this.RedirectUrl));
        }
        protected override HttpRequestCommand CreateGetAccessTokenCommand(String code)
        {
            String url = "https://oauth.live.com/token";
            var cm = new HttpRequestCommand(url);
            cm.MethodName = HttpMethodName.Post;
            var d = new Dictionary<String, String>();
            d["grant_type"] = "authorization_code";
            d["code"] = code;
            d["client_id"] = this.ClientID;
            d["client_secret"] = this.ClientSecret;
            d["redirect_uri"] = this.RedirectUrl;
            cm.SetBodyStream(new HttpBodyFormUrlEncodedData(Encoding.UTF8, d));
            return cm;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        private void GetResponseBodyText(WindowsLiveCommand command, Action<String> callback)
        {
            String url = String.Format("https://apis.live.net/v5.0/{0}?access_token={1}{2}", command.GraphApiPath
                , HttpClient.UrlEncode(this.AccessToken.Value)
                , command.UrlParameter);
            url += String.Format("&callback={0}", Callbackkey);

            var cm = new HttpRequestCommand(url);
            cm.MethodName = command.MethodName;
            cm.ContentType = command.ContentType;

            if (command.MethodName == HttpMethodName.Post
             || command.MethodName == HttpMethodName.Put
             || command.MethodName == HttpMethodName.Move
             || command.MethodName == HttpMethodName.Copy)
            {
                cm.SetBodyStream(command.Data);
            }
            this.GetBodyText(cm, res => callback(Regex.Match(res, @"{.*}", RegexOptions.IgnoreCase).Value));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="callback"></param>
        public void GetUser(Action<User> callback)
        {
            this.GetUser(new GetUserCommand(""), callback);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="callback"></param>
        public void GetUser(String id, Action<User> callback)
        {
            this.GetUser(new GetUserCommand(id), callback);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetUser(GetUserCommand command, Action<User> callback)
        {
            this.GetResponseBodyText(command, res => callback(new User(res)));
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetFiles(GetFilesCommand command, Action<LiveObjectCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new LiveObjectCollection(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetFile(GetFileCommand command, Action<File> callback)
        {
            this.GetResponseBodyText(command, res => callback(new File(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="folderID"></param>
        /// <param name="callback"></param>
        public void GetFolder(String folderID, Action<Folder> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(folderID), res => callback(new Folder(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetFolder(GetFolderCommand command, Action<Folder> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Folder(res)));
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileID"></param>
        /// <param name="callback"></param>
        public void GetFile(String fileID, Action<File> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(fileID), res => callback(new File(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="photoID"></param>
        /// <param name="callback"></param>
        public void GetPhoto(String photoID, Action<Photo> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(photoID), res => callback(new Photo(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="videoID"></param>
        /// <param name="callback"></param>
        public void GetVideo(String videoID, Action<Video> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(videoID), res => callback(new Video(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="audioID"></param>
        /// <param name="callback"></param>
        public void GetAudio(String audioID, Action<Audio> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(audioID), res => callback(new Audio(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="albumID"></param>
        /// <param name="callback"></param>
        public void GetAlbum(String albumID, Action<Album> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(albumID), res => callback(new Album(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetApplications(GetApplicationsCommand command, Action<ApplicationCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new ApplicationCollection(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateApplication(CreateApplicationCommand command, Action<Application> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Application(res)));
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateFileProperties(UpdateFileCommand command, Action<File> callback)
        {
            this.GetResponseBodyText(command, res => callback(new File(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateFolderProperties(UpdateFileCommand command, Action<Folder> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Folder(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdatePhotoProperties(UpdateFileCommand command, Action<Photo> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Photo(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateAudioProperties(UpdateFileCommand command, Action<Audio> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Audio(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateVideoProperties(UpdateFileCommand command, Action<Video> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Video(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateAlbumProperties(UpdateFileCommand command, Action<Album> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Album(res)));
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileID"></param>
        /// <param name="callback"></param>
        public void GetDownloadFilePath(String fileID, Action<String> callback)
        {
            this.GetResponseBodyText(new GetFileCommand(fileID, ActFLG.GetDownloadLink), res => callback(new Result(res).Location));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="location"></param>
        /// <param name="callback"></param>
        public void DownloadFile(String location, Action<Byte[]> callback)
        {
            this.GetResponse(location, res => callback(res.BodyData));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void PostFile(PostFileCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Result(res).ID));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void DeleteFile(DeleteFileCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void DeleteFolder(DeleteFolderCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetEvent(GetEventCommand command, Action<Event> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Event(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetEvents(GetEventsCommnad command, Action<EventCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new EventCollection(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void DeleteEvent(DeleteEventCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateEvent(CreateEventCommand command, Action<Event> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Event(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetPermissions(GetPermissionsCommnad command, Action<Permissions> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Permissions(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetTag(GetTagCommand command, Action<Tag> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Tag(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetTags(GetTagsCommnad command, Action<TagCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new TagCollection(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UploadFile(UploadFileCommand command, Action<Result> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Result(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateFolder(PostCommand command, Action<Folder> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Folder(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateAlbum(PostCommand command, Action<Album> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Album(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateActivity(CreateActivityCommand command, Action<Activity> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Activity(res)));
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void MoveFileFolder(MoveFileCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CopyFileFolder(CopyFileCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetContacts(GetContactsCommand command, Action<Contacts> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Contacts(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="callback"></param>
        public void GetContacts(Action<Contacts> callback)
        {
            this.GetContacts(new GetContactsCommand(), callback);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetComments(GetCommentsCommnad command, Action<CommentCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new CommentCollection(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="commentID"></param>
        /// <param name="callback"></param>
        public void GetComment(String commentID, Action<Comment> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(commentID), res => callback(new Comment(res)));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetCalendars(GetCalendarsCommand command, Action<CalendarCollection> callback)
        {
            this.GetResponseBodyText(command, res => callback(new CalendarCollection(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="calendarID"></param>
        /// <param name="callback"></param>
        public void GetCalendar(String calendarID, Action<Calendar> callback)
        {
            this.GetResponseBodyText(new WindowsLiveCommand(calendarID), res => callback(new Calendar(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void CreateCalendar(CreateCalendarCommand command, Action<Calendar> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Calendar(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void UpdateCalender(UpdateCalendarCommand command, Action<Calendar> callback)
        {
            this.GetResponseBodyText(command, res => callback(new Calendar(res)));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void DeleteCalendar(DeleteCalendarCommand command, Action<String> callback)
        {
            this.GetResponseBodyText(command, s => callback(s));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="callback"></param>
        public void GetFriends(GetFriendsCommand command, Action<FriendCollertion> callback)
        {
            this.GetResponseBodyText(command, res => callback(new FriendCollertion(res)));
        }
    }
}

